#include "DrawWidget.h"
#include <QDebug>
#define mout qDebug() <<"["<<__FILE__<<":"<<__LINE__<<"]"


double R = 0.3;
double G = 0.2;
double B = 0.0;

DrawWidget::DrawWidget(GeoMap *map){
    Xmin=INT32_MAX;
    Xmax=-INT32_MAX;
    Ymin=INT32_MAX;
    Ymax=-INT32_MAX;
    Scale=1;
    DCLeft=0;
    DCBottom=0;
    this->map = map;
}

void DrawWidget::paintGL(){
    glViewport(int(DCLeft), int(DCBottom), int(DCWidth), int(DCHeight));
    //MapPrj();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0f,1.0f,1.0f,0.0f);
    drawMap(map);
    glEnd();
}

void DrawWidget::resizeGL(int w, int h){
    glViewport(0,0,w,h);
    this->DCWidth=w;
    this->DCHeight=h;
}

void DrawWidget::initializeGL(){
    initializeOpenGLFunctions();
}

//地图绘制函数
void DrawWidget::drawMap(GeoMap *map)
{
    for(int i = map->getLayerSize() - 1;i>=0;--i){
        this->drawLayer(map->getLayer(i));
    }
}

//图层绘制函数
void DrawWidget::drawLayer(GeoLayer *layer)
{
    for(int i =0;i<layer->getObjSize();++i){
        this->drawObject(layer->getObject(i));
    }
}

//对象绘制函数
void DrawWidget::drawObject(GeoObject *obj)
{
    QString type = obj->getPropertiesValue("type").toString();
    if(type == "Point"){
        LonLat temp = static_cast<GeoPoint*>(obj)->getData();
        R = static_cast<GeoPoint*>(obj)->getR();
        G = static_cast<GeoPoint*>(obj)->getG();
        B = static_cast<GeoPoint*>(obj)->getB();
        glPointSize(4.0f);
        glBegin(GL_POINTS);
        glColor3d(R,G,B);
        glVertex2d(temp.getLongitude(),temp.getLatitude());
        glEnd();
    }
    else if(type == "LineString"){
        QList<LonLat> temp = static_cast<GeoPolyLine*>(obj)->getData();
        R = static_cast<GeoPolyLine*>(obj)->getR();
        G = static_cast<GeoPolyLine*>(obj)->getG();
        B = static_cast<GeoPolyLine*>(obj)->getB();
        glLineWidth(1);
        glBegin(GL_LINE_STRIP);
        glColor3d(R,G,B);
        for(int k = 0;k<temp.size();++k){
            double pt[] = {temp.at(k).getLongitude(),temp.at(k).getLatitude()};
            glVertex2dv(pt);
        }
        glEnd();
    }
    else if(type == "Polygon"){
//        QList<LonLat> temp = static_cast<GeoPolygon*>(obj)->getData();
//        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
//        glFrontFace(GL_CCW);
//        R=static_cast<GeoPolygon*>(obj)->getFillR();
//        G=static_cast<GeoPolygon*>(obj)->getFillG();
//        B=static_cast<GeoPolygon*>(obj)->getFillB();
//        glLineWidth(1);
//        glColor3f(R,G,B);
//        glBegin(GL_POLYGON);
//        for (int q=0;q<temp.size();q++)
//        {
//            double pt1[]={(temp.at(q).longitude-((this->layer->Xmax+this->layer->Xmin)/2))/((this->layer->Xmax-this->layer->Xmin)/2),(temp.at(q).latitude-((this->layer->Ymax+this->layer->Ymin)/2))/((this->layer->Xmax-this->layer->Xmin)/2)};
//            glVertex2dv (pt1);
//        }
//        glEnd();
//        R=static_cast<GeoPolygon*>(obj)->getLineR();
//        G=static_cast<GeoPolygon*>(obj)->getLineG();
//        B=static_cast<GeoPolygon*>(obj)->getLineB();
//        glLineWidth(1);
//        glBegin(GL_LINE_LOOP);
//        glColor3d(R, G, B);
//        for (int q=0;q<temp.size();q++)
//        {
//            double pt1[]={(temp.at(q).longitude-((this->layer->Xmax+this->layer->Xmin)/2))/((this->layer->Xmax-this->layer->Xmin)/2),(temp.at(q).latitude-((this->layer->Ymax+this->layer->Ymin)/2))/((this->layer->Xmax-this->layer->Xmin)/2)};
//            glVertex2dv (pt1);
//        }
//        glEnd();



        QList<LonLat> temp = static_cast<GeoPolygon*>(obj)->getData();
        R = static_cast<GeoPolygon*>(obj)->getFillR();
        G = static_cast<GeoPolygon*>(obj)->getFillG();
        B = static_cast<GeoPolygon*>(obj)->getFillB();

        StartTess(temp);
        R = static_cast<GeoPolygon*>(obj)->getLineR();
        G = static_cast<GeoPolygon*>(obj)->getLineG();
        B = static_cast<GeoPolygon*>(obj)->getLineB();
        glLineWidth(1);
        glBegin(GL_LINE_LOOP);
        glColor3d(R,G,B);
        for(int k = 0;k<temp.size();++k){
            double pt[] = {temp.at(k).getLongitude(),temp.at(k).getLatitude()};
            glVertex2dv(pt);
        }
        glEnd();
    }
    else{

    }
}
void DrawWidget::getMapData()
{


}
\
//地图投影
void DrawWidget::MapPrj()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    double temp1 = PrjRight-PrjLeft;
    double temp2 = PrjTop-PrjBottom;
    double Oriwidth=this->width();
    double OriHeight=this->height();
    double ViewRate = Oriwidth/OriHeight;
    double DataRate = temp1/temp2;

    if(DataRate>=ViewRate)
        glOrtho(PrjLeft,PrjRight,(PrjBottom+PrjTop)/2-temp1/ViewRate/2,(PrjBottom+PrjTop)/2+temp1/ViewRate/2,-100,100);
    if(DataRate<ViewRate)
        glOrtho((PrjLeft+PrjRight)/2-ViewRate*temp2/2,(PrjRight+PrjLeft)/2+ViewRate*temp2/2,PrjBottom,PrjTop,-100,100);
}

void DrawWidget::GetOriScale()
{
    PrjLeft=Xmin;
    PrjRight=Xmax;
    PrjTop=Ymax;
    PrjBottom=Ymin;
}


//多边形处理
void DrawWidget::vertexCallback(GLvoid *vertex)
{
    GLdouble *pointer =(GLdouble *)vertex;
    glVertex3dv(pointer);
}

void DrawWidget::beginCallback(GLenum which)
{
    glBegin(which);
    glColor3d(R,G,B);
}

void DrawWidget::endCallback()
{
    glEnd();
}

void DrawWidget::errorCallback(GLenum errorcode)
{
    const GLubyte *estring;
    estring = gluErrorString(errorcode);
    exit(0);

}

void DrawWidget::combineCallback(GLdouble coords[], GLdouble *vertex_data[], GLfloat weight[], GLdouble **dataOut)
{
    GLdouble *vertex;
    int i;
    vertex = (GLdouble *) malloc(6 * sizeof(GLdouble));
    vertex[0] = coords[0];
    vertex[1] = coords[1];
    vertex[2] = coords[2];
    //    vertex[3] = 1;
    //    vertex[4] = 0;
    //    vertex[5] = 0;
    //    vertex[6] = 0;

    //    mout<<coords[0]<<" ";
    //    mout<<coords[1]<<" ";
    //    mout<<coords[2]<<" ";
    for (i = 3; i < 7; i++)
    {
        //       vertex[i] = weight[0] * vertex_data[0][i];
        //            + weight[1] * vertex_data[1][i]
        //            + weight[2] * vertex_data[2][i]
        //
    }
    *dataOut = vertex;
}

void DrawWidget::StartTess(QList<LonLat> temp)
{
    int pSize = temp.size();
    double **PTS = new double*[pSize];
    for(int i = 0;i<pSize;++i){
        PTS[i] = new double[3];
        for(int k = 0;k<temp.size();++k){
            PTS[k][0] = temp.at(k).getLongitude();
            PTS[k][1] = temp.at(k).getLatitude();
            PTS[k][2] = 0;
        }
    }

    GLUtesselator *tobj = gluNewTess();

    gluTessCallback(tobj,GLU_TESS_VERTEX,(void(_stdcall*)())glVertex3dv);
    gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK *)())beginCallback);
    gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK *)())endCallback);
    gluTessCallback(tobj, GLU_TESS_ERROR, (void (CALLBACK *)())errorCallback);
    gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK *)())combineCallback);


    gluTessBeginPolygon(tobj, nullptr);
    gluTessBeginContour(tobj);



    for (int q=0;q<temp.size();q++){
        gluTessVertex(tobj,PTS[q],PTS[q]);
    }
    gluTessEndContour(tobj);
    gluTessEndPolygon(tobj);
    gluDeleteTess(tobj);


    for (int i=0;i<pSize;i++) {
        delete[] PTS[i];
        PTS[i]=nullptr;
    }
    delete[] PTS;
    PTS=nullptr;
}

DrawWidget::~DrawWidget(){
    delete map;
}








